home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Cream of the Crop 20
/
Cream of the Crop 20 (Terry Blount) (1996).iso
/
program
/
vol15n10.zip
/
MULTIL.ZIP
/
MLSRC.ZIP
/
MSDEV
/
PROJECTS
/
MLAUNCH
/
MLAUNCH.CPP
< prev
next >
Wrap
C/C++ Source or Header
|
1996-04-14
|
12KB
|
440 lines
// MultiLaunch Shell Extension
// (C)1996 By John Lam
#include "stdafx.h"
#include <windows.h>
#include <initguid.h>
#include <shlobj.h>
#include "Resource.h"
#include "MLaunch.h"
/////////////////////////////////////////////////////////////////////////////
// Nonmember function prototypes
STDAPI DllGetClassObject (REFCLSID, REFIID, LPVOID*);
STDAPI DllCanUnloadNow ();
STDAPI DllRegisterServer ();
STDAPI DllUnregisterServer ();
void UpdateRegistry(BOOL);
HKEY CreateRegKey(CString, CString);
void DeleteRegKey(CString);
void CreateRegValue(HKEY, CString, CString);
UINT CALLBACK AfxPropPageCallback(HWND, UINT message, LPPROPSHEETPAGE pPropPage);
UINT CALLBACK PropPageCallback(HWND, UINT message, LPPROPSHEETPAGE pPropPage);
// Helper functions
CString GetFilenameExtension(CString);
/////////////////////////////////////////////////////////////////////////////
// Global variables
UINT g_cRefThisDll = 0; // Reference count for this DLL
/////////////////////////////////////////////////////////////////////////////
// Exported functions
STDAPI DllGetClassObject (REFCLSID rclsid, REFIID riid, LPVOID* ppvObj)
{
*ppvObj = NULL;
if (rclsid != CLSID_MultiLaunchPropSheet)
return CLASS_E_CLASSNOTAVAILABLE;
CClassFactory* pClassFactory = new CClassFactory;
if (pClassFactory == NULL)
return E_OUTOFMEMORY;
HRESULT hr = pClassFactory->QueryInterface (riid, ppvObj);
pClassFactory->Release ();
return hr;
}
STDAPI DllCanUnloadNow ()
{
return (g_cRefThisDll == 0) ? S_OK : S_FALSE;
}
STDAPI DllRegisterServer(void)
{
// Code to autoregister the server into the registry
UpdateRegistry(TRUE);
return S_OK;
}
STDAPI DllUnregisterServer(void)
{
UpdateRegistry(FALSE);
return S_OK;
}
// Helper function that registers and unregisters the DLL
void UpdateRegistry(BOOL Register)
{
HKEY hKey;
CString strCLSID = STRCLSID_MultiLaunchPropSheet;
CString strProgID = STRPROGID_MultiLaunchPropSheet;
CString strDescription = STRDESCRIPTION_MultiLaunchPropSheet;
CString strFilename;
// Get the full path to this dll
GetModuleFileName(AfxGetInstanceHandle(), strFilename.GetBuffer(260), 260);
strFilename.ReleaseBuffer();
if (Register) {
// Register the DLL
(void) CreateRegKey(strProgID, strDescription);
(void) CreateRegKey(strProgID + "\\CLSID", strCLSID);
(void) CreateRegKey("CLSID\\" + strCLSID, strDescription);
(void) CreateRegKey("CLSID\\" + strCLSID + "\\ProgID", strProgID);
hKey = CreateRegKey("CLSID\\" + strCLSID + "\\InProcServer32", strFilename);
CreateRegValue(hKey, "ThreadingModel", "Apartment");
// Register the Context Menu Handler
(void) CreateRegKey("*\\shellex\\ContextMenuHandlers\\" + strProgID, strCLSID);
// Register the Property Sheet Handler
(void) CreateRegKey("*\\shellex\\PropertySheetHandlers\\" + strProgID, strCLSID);
}
else {
// Unregister the DLL
DeleteRegKey(strProgID);
DeleteRegKey(strProgID + "\\CLSID");
DeleteRegKey("CLSID\\" + strCLSID);
DeleteRegKey("CLSID\\" + strCLSID + "\\ProgID");
DeleteRegKey("CLSID\\" + strCLSID + "\\InProcServer32");
// Unregister the Context Menu Handler
DeleteRegKey("*\\shellex\\ContextMenuHandlers\\" + strProgID);
// Unregister the Property Sheet Handler
DeleteRegKey("*\\shellex\\PropertySheetHandlers\\" + strProgID);
}
}
// Helper functions for creating and destroying registry keys
HKEY CreateRegKey(CString strKey, CString strValue)
{
HKEY hKey;
DWORD Disposition;
RegCreateKeyEx(HKEY_CLASSES_ROOT, strKey, 0, strValue.LockBuffer(), REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &hKey, &Disposition);
strValue.UnlockBuffer();
RegSetValueEx(hKey, NULL, 0, REG_SZ, (BYTE*)strValue.LockBuffer(), strValue.GetLength() + 1);
strValue.UnlockBuffer();
return hKey;
}
void DeleteRegKey(CString strKey)
{
RegDeleteKey(HKEY_CLASSES_ROOT, strKey);
}
void CreateRegValue(HKEY hKey, CString strValueName, CString strValue)
{
RegSetValueEx(hKey, strValueName, 0, REG_SZ, (BYTE*)strValue.LockBuffer(), strValue.GetLength() + 1);
strValue.UnlockBuffer();
}
/////////////////////////////////////////////////////////////////////////////
// CClassFactory member functions
CClassFactory::CClassFactory ()
{
m_cRef = 1;
g_cRefThisDll++;
}
CClassFactory::~CClassFactory ()
{
g_cRefThisDll--;
}
STDMETHODIMP CClassFactory::QueryInterface (REFIID riid, LPVOID* ppvObj)
{
*ppvObj = NULL;
HRESULT hr = E_NOINTERFACE;
if ((riid == IID_IUnknown) || (riid == IID_IClassFactory)) {
*ppvObj = this;
hr = NOERROR;
m_cRef++;
}
return hr;
}
STDMETHODIMP_(ULONG) CClassFactory::AddRef ()
{
return ++m_cRef;
}
STDMETHODIMP_(ULONG) CClassFactory::Release ()
{
if (--m_cRef == 0)
delete this;
return m_cRef;
}
STDMETHODIMP CClassFactory::CreateInstance (LPUNKNOWN pUnkOuter, REFIID riid,
LPVOID* ppvObj)
{
*ppvObj = NULL;
if (pUnkOuter != NULL)
return CLASS_E_NOAGGREGATION;
CShellExtension* pShellExtension = new CShellExtension;
if (pShellExtension == NULL)
return E_OUTOFMEMORY;
HRESULT hr = pShellExtension->QueryInterface (riid, ppvObj);
if (hr == S_OK)
pShellExtension->Release ();
return hr;
}
STDMETHODIMP CClassFactory::LockServer (BOOL fLock)
{
return E_NOTIMPL;
}
/////////////////////////////////////////////////////////////////////////////
// CShellExtension member functions
CShellExtension::CShellExtension ()
{
// !!!!! BUG
// VC++ 4.0 Incorrectly decrements m_cRef 1 too many times when building
// a Win32 Debug version of the application. The macro here detects and adjusts
// the number to 2 when we are building the debug version of the application
// The reason for this is unknown.
/* #ifdef _DEBUG
m_cRef = 2; // BUG! in DEBUG build
#endif
#ifndef _DEBUG
m_cRef = 1; // Correctly compiled in RELEASE build
#endif */
// The above bug is FIXED in VC++ 4.1!! Hooray!
//ASSERT(FALSE);
m_cRef = 1;
g_cRefThisDll++;
}
CShellExtension::~CShellExtension ()
{
g_cRefThisDll--;
}
STDMETHODIMP CShellExtension::QueryInterface (REFIID riid, LPVOID* ppvObj)
{
*ppvObj = NULL;
HRESULT hr = E_NOINTERFACE;
if (riid == IID_IUnknown) {
*ppvObj = (LPUNKNOWN) (LPSHELLPROPSHEETEXT) this;
hr = NOERROR;
m_cRef++;
}
else if (riid == IID_IShellPropSheetExt) {
*ppvObj = (LPSHELLPROPSHEETEXT) this;
hr = NOERROR;
m_cRef++;
}
else if (riid == IID_IShellExtInit) {
*ppvObj = (LPSHELLEXTINIT) this;
hr = NOERROR;
m_cRef++;
}
else if (riid == IID_IContextMenu) {
*ppvObj = (LPCONTEXTMENU) this;
hr = NOERROR;
m_cRef++;
}
return hr;
}
STDMETHODIMP_(ULONG) CShellExtension::AddRef ()
{
return ++m_cRef;
}
STDMETHODIMP_(ULONG) CShellExtension::Release ()
{
if (--m_cRef == 0)
delete this;
return m_cRef;
}
STDMETHODIMP CShellExtension::AddPages (LPFNADDPROPSHEETPAGE lpfnAddPage,
LPARAM lParam)
{
HPROPSHEETPAGE hPage;
CMLPage* pMLPage = new CMLPage;
// Setup reference counting
pMLPage->m_psp.pcRefParent = &g_cRefThisDll;
pMLPage->m_psp.dwFlags = pMLPage->m_psp.dwFlags | PSP_USEREFPARENT;
// Hook into the PropPageCallback so that I can destroy the CMLPage object
// when Windows destroys the window represented by CMLPage.
pMLPage->m_psp.pfnCallback = PropPageCallback;
// Save filename in the Property Page Class CMLPage
pMLPage->SetFilename(m_szFile);
hPage = CreatePropertySheetPage (&pMLPage->m_psp);
if (hPage != NULL)
if (!lpfnAddPage (hPage, lParam))
DestroyPropertySheetPage (hPage);
return NOERROR;
}
STDMETHODIMP CShellExtension::ReplacePage (UINT uPageID,
LPFNADDPROPSHEETPAGE lpfnReplaceWith, LPARAM lParam)
{
return E_FAIL;
}
STDMETHODIMP CShellExtension::Initialize (LPCITEMIDLIST pidlFolder,